home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / SLAX 6.0.8 / slax-6.0.8.iso / slax / base / 006-devel.lzm / usr / include / isc / refcount.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-09-17  |  6.0 KB  |  234 lines

  1. /*
  2.  * Copyright (C) 2004, 2005  Internet Systems Consortium, Inc. ("ISC")
  3.  * Copyright (C) 2001, 2003  Internet Software Consortium.
  4.  *
  5.  * Permission to use, copy, modify, and distribute this software for any
  6.  * purpose with or without fee is hereby granted, provided that the above
  7.  * copyright notice and this permission notice appear in all copies.
  8.  *
  9.  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  10.  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  11.  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  12.  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  13.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  14.  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  15.  * PERFORMANCE OF THIS SOFTWARE.
  16.  */
  17.  
  18. /* $Id: refcount.h,v 1.6.18.5 2005/07/12 01:22:31 marka Exp $ */
  19.  
  20. #ifndef ISC_REFCOUNT_H
  21. #define ISC_REFCOUNT_H 1
  22.  
  23. #include <isc/atomic.h>
  24. #include <isc/lang.h>
  25. #include <isc/mutex.h>
  26. #include <isc/platform.h>
  27. #include <isc/types.h>
  28. #include <isc/util.h>
  29.  
  30. /*! \file
  31.  * \brief Implements a locked reference counter.  
  32.  *
  33.  * These functions may actually be
  34.  * implemented using macros, and implementations of these macros are below.
  35.  * The isc_refcount_t type should not be accessed directly, as its contents
  36.  * depend on the implementation.
  37.  */
  38.  
  39. ISC_LANG_BEGINDECLS
  40.  
  41. /*
  42.  * Function prototypes
  43.  */
  44.  
  45. /* 
  46.  * isc_result_t
  47.  * isc_refcount_init(isc_refcount_t *ref, unsigned int n);
  48.  *
  49.  * Initialize the reference counter.  There will be 'n' initial references.
  50.  *
  51.  * Requires:
  52.  *    ref != NULL
  53.  */
  54.  
  55. /*
  56.  * void
  57.  * isc_refcount_destroy(isc_refcount_t *ref);
  58.  *
  59.  * Destroys a reference counter.
  60.  *
  61.  * Requires:
  62.  *    ref != NULL
  63.  *    The number of references is 0.
  64.  */
  65.  
  66. /*
  67.  * void
  68.  * isc_refcount_increment(isc_refcount_t *ref, unsigned int *targetp);
  69.  * isc_refcount_increment0(isc_refcount_t *ref, unsigned int *targetp);
  70.  *
  71.  * Increments the reference count, returning the new value in targetp if it's
  72.  * not NULL.  The reference counter typically begins with the initial counter
  73.  * of 1, and will be destroyed once the counter reaches 0.  Thus,
  74.  * isc_refcount_increment() additionally requires the previous counter be
  75.  * larger than 0 so that an error which violates the usage can be easily
  76.  * caught.  isc_refcount_increment0() does not have this restriction.
  77.  *
  78.  * Requires:
  79.  *    ref != NULL.
  80.  */
  81.  
  82. /*
  83.  * void
  84.  * isc_refcount_decrement(isc_refcount_t *ref, unsigned int *targetp);
  85.  *
  86.  * Decrements the reference count,  returning the new value in targetp if it's
  87.  * not NULL.
  88.  *
  89.  * Requires:
  90.  *    ref != NULL.
  91.  */
  92.  
  93.  
  94. /*
  95.  * Sample implementations
  96.  */
  97. #ifdef ISC_PLATFORM_USETHREADS
  98. #ifdef ISC_PLATFORM_HAVEXADD
  99.  
  100. #define ISC_REFCOUNT_HAVEATOMIC 1
  101.  
  102. typedef struct isc_refcount {
  103.     isc_int32_t refs;
  104. } isc_refcount_t;
  105.  
  106. #define isc_refcount_destroy(rp) (REQUIRE((rp)->refs == 0))
  107. #define isc_refcount_current(rp) ((unsigned int)((rp)->refs))
  108.  
  109. #define isc_refcount_increment0(rp, tp)                \
  110.     do {                            \
  111.         unsigned int *_tmp = (unsigned int *)(tp);    \
  112.         isc_int32_t prev;                \
  113.         prev = isc_atomic_xadd(&(rp)->refs, 1);        \
  114.         if (_tmp != NULL)                \
  115.             *_tmp = prev + 1;            \
  116.     } while (0)
  117.  
  118. #define isc_refcount_increment(rp, tp)                \
  119.     do {                            \
  120.         unsigned int *_tmp = (unsigned int *)(tp);    \
  121.         isc_int32_t prev;                \
  122.         prev = isc_atomic_xadd(&(rp)->refs, 1);        \
  123.         REQUIRE(prev > 0);                \
  124.         if (_tmp != NULL)                \
  125.             *_tmp = prev + 1;            \
  126.     } while (0)
  127.  
  128. #define isc_refcount_decrement(rp, tp)                \
  129.     do {                            \
  130.         unsigned int *_tmp = (unsigned int *)(tp);    \
  131.         isc_int32_t prev;                \
  132.         prev = isc_atomic_xadd(&(rp)->refs, -1);    \
  133.         REQUIRE(prev > 0);                \
  134.         if (_tmp != NULL)                \
  135.             *_tmp = prev - 1;            \
  136.     } while (0)
  137.  
  138. #else  /* ISC_PLATFORM_HAVEXADD */
  139.  
  140. typedef struct isc_refcount {
  141.     int refs;
  142.     isc_mutex_t lock;
  143. } isc_refcount_t;
  144.  
  145. /*% Destroys a reference counter. */
  146. #define isc_refcount_destroy(rp)            \
  147.     do {                        \
  148.         REQUIRE((rp)->refs == 0);        \
  149.         DESTROYLOCK(&(rp)->lock);        \
  150.     } while (0)
  151.  
  152. #define isc_refcount_current(rp) ((unsigned int)((rp)->refs))
  153.  
  154. /*% Increments the reference count, returning the new value in targetp if it's not NULL. */
  155. #define isc_refcount_increment0(rp, tp)                \
  156.     do {                            \
  157.         unsigned int *_tmp = (unsigned int *)(tp);    \
  158.         LOCK(&(rp)->lock);                \
  159.         ++((rp)->refs);                    \
  160.         if (_tmp != NULL)                \
  161.             *_tmp = ((rp)->refs);            \
  162.         UNLOCK(&(rp)->lock);                \
  163.     } while (0)
  164.  
  165. #define isc_refcount_increment(rp, tp)                \
  166.     do {                            \
  167.         unsigned int *_tmp = (unsigned int *)(tp);    \
  168.         LOCK(&(rp)->lock);                \
  169.         REQUIRE((rp)->refs > 0);            \
  170.         ++((rp)->refs);                    \
  171.         if (_tmp != NULL)                \
  172.             *_tmp = ((rp)->refs);            \
  173.         UNLOCK(&(rp)->lock);                \
  174.     } while (0)
  175.  
  176. /*% Decrements the reference count,  returning the new value in targetp if it's not NULL. */
  177. #define isc_refcount_decrement(rp, tp)                \
  178.     do {                            \
  179.         unsigned int *_tmp = (unsigned int *)(tp);    \
  180.         LOCK(&(rp)->lock);                \
  181.         REQUIRE((rp)->refs > 0);            \
  182.         --((rp)->refs);                    \
  183.         if (_tmp != NULL)                \
  184.             *_tmp = ((rp)->refs);            \
  185.         UNLOCK(&(rp)->lock);                \
  186.     } while (0)
  187.  
  188. #endif /* ISC_PLATFORM_HAVEXADD */
  189. #else  /* ISC_PLATFORM_USETHREADS */
  190.  
  191. typedef struct isc_refcount {
  192.     int refs;
  193. } isc_refcount_t;
  194.  
  195. #define isc_refcount_destroy(rp) (REQUIRE((rp)->refs == 0))
  196. #define isc_refcount_current(rp) ((unsigned int)((rp)->refs))
  197.  
  198. #define isc_refcount_increment0(rp, tp)                    \
  199.     do {                                \
  200.         unsigned int *_tmp = (unsigned int *)(tp);        \
  201.         int _n = ++(rp)->refs;                    \
  202.         if (_tmp != NULL)                    \
  203.             *_tmp = _n;                    \
  204.     } while (0)
  205.  
  206. #define isc_refcount_increment(rp, tp)                    \
  207.     do {                                \
  208.         unsigned int *_tmp = (unsigned int *)(tp);        \
  209.         int _n;                            \
  210.         REQUIRE((rp)->refs > 0);                \
  211.         _n = ++(rp)->refs;                    \
  212.         if (_tmp != NULL)                    \
  213.             *_tmp = _n;                    \
  214.     } while (0)
  215.  
  216. #define isc_refcount_decrement(rp, tp)                    \
  217.     do {                                \
  218.         unsigned int *_tmp = (unsigned int *)(tp);        \
  219.         int _n;                            \
  220.         REQUIRE((rp)->refs > 0);                \
  221.         _n = --(rp)->refs;                    \
  222.         if (_tmp != NULL)                    \
  223.             *_tmp = _n;                    \
  224.     } while (0)
  225.  
  226. #endif /* ISC_PLATFORM_USETHREADS */
  227.  
  228. isc_result_t
  229. isc_refcount_init(isc_refcount_t *ref, unsigned int n);
  230.  
  231. ISC_LANG_ENDDECLS
  232.  
  233. #endif /* ISC_REFCOUNT_H */
  234.